home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Video
/
World of Video.iso
/
datafiles
/
misc
/
hardware
/
1541_to_amiga
/
1541.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-13
|
14KB
|
399 lines
;/*
sc DisAsm=ram:1541.s 1541.c ProgramName=1541 ObjectName=ram: Ignore=73+306 GST=include:all.gst GSTImm NoIcon NoStackCheck UnsignedChar Parm=Register Opt OptSched OptInLocal OptDep=100 OptRDep=100 CommentNest Link
quit
*/
/*
1541 disk-to-file convertor for A1020
Copyright © 1994 by Dan Babcock
Compiled with SAS/C V6.51
*/
typedef short bool; /* enum bool { FALSE, TRUE }; */
/* Buffers */
#define RAWBUFSIZE 9000
#define MAXBITPTR RAWBUFSIZE*8-400*8
#define DISKSIZE 683*256
static __chip char RawBuffer[RAWBUFSIZE];
static __far char DecodedBuffer[DISKSIZE];
/* Command line parsing */
enum cmdargs { DRIVE, FILENAME, RETRY, TOP, OFFSET, NUMARGS };
static struct RDArgs *rdargs;
static LONG args[NUMARGS];
/* Device access */
static struct MsgPort *port;
static struct IOStdReq *io;
static bool DevOpen;
/* Misc */
static char ver[]="$VER: 1541 1.01 (17.6.94)\n";
long __OSlibversion = 37;
struct Library *DiskBase;
static unsigned RetryCount=10;
/* Finish disk I/O */
static void FinishIO(void)
{
io->io_Command = TD_MOTOR;
io->io_Length = 0;
DoIO((struct IORequest *)io);
}
/* Autotermination routine */
void _STDautoterm(void)
{
/* Free misc */
if (DevOpen) {
FinishIO();
CloseDevice((struct IORequest *)io);
}
if (io) DeleteIORequest(io);
if (port) DeleteMsgPort(port);
if (rdargs) FreeArgs(rdargs);
}
/* Read a raw track */
/* Unfortunately we can't use TD_RAWREAD, since we need to set 4us/bit mode */
static void RawRead(unsigned track)
{
static struct DiscResourceUnit diskunit; /* initialized to zero because of static */
// volatile struct CIA *ciaa=(void*)0xbfe001;
volatile struct CIA *ciab=(void*)0xbfd000;
volatile struct Custom *custom=(void*)0xdff000;
/* TD motor on */
io->io_Command = TD_MOTOR;
io->io_Length = 1;
DoIO((struct IORequest *)io);
/* Seek to the proper track */
io->io_Command = TD_SEEK;
io->io_Offset = track*5632;
if (args[OFFSET])
io->io_Offset += (*(int*)args[OFFSET])*11264;
if (io->io_Offset > 11264*39)
io->io_Offset = 0;
DoIO((struct IORequest *)io);
/* Take over the disk hardware and read the track "by hand" */
/* (which is a pain even when taking some shortcuts) */
/* Here goes...*/
/* get the resource */
diskunit.dru_Message.mn_ReplyPort=port;
diskunit.dru_Message.mn_Node.ln_Name="1541 disk reader";
while (!GetUnit((struct DiskResourceUnit*)&diskunit)) {
WaitPort(port);
GetMsg(port); /* important! remove message */
}
/* set up CIA bits, turn on motor, wait for motor */
ciab->ciaprb |= CIAF_DSKSEL0|CIAF_DSKSEL1|CIAF_DSKSEL2|CIAF_DSKSEL3;
ciab->ciaprb &= ~CIAF_DSKMOTOR;
ciab->ciaprb &= ~(1<<(*(int *)args[DRIVE]+3));
if (track & 1)
ciab->ciaprb &= ~CIAF_DSKSIDE;
else
ciab->ciaprb |= CIAF_DSKSIDE;
// while (ciaa->ciapra & CIAF_DSKRDY)
// ;
/* set up disk hardware */
custom->adkcon = ADKF_WORDSYNC|ADKF_MSBSYNC|ADKF_FAST;
custom->intreq = INTF_DSKBLK;
custom->dskpt = RawBuffer;
/* now for the main event...drum roll please */
custom->dsklen = (RAWBUFSIZE/2)|(1<<15);
custom->dsklen = (RAWBUFSIZE/2)|(1<<15);
while (!(custom->intreqr & INTF_DSKBLK))
;
/* done! */
custom->intreq = INTF_DSKBLK;
custom->dsklen = DSKDMAOFF;
GiveUnit();
}
static unsigned bitptr; /* Bit pointer to raw data (offset from RawBuffer) */
/* Grab 10 bits of GCR from RawBuffer+bitptr and return a byte of decoded data */
/* Note: No checking for "end of buffer" condition! */
static __inline UBYTE GetByte(void)
{
static UBYTE GCRTable[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x80,0x81,0x00,0x8C,0x84,0x85,
0x00,0x00,0x82,0x83,0x00,0x8F,0x86,0x87,0x00,0x89,0x8A,0x8B,0x00,0x8D,0x8E,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x01,0x00,0x0C,0x04,0x05,
0x00,0x00,0x02,0x03,0x00,0x0F,0x06,0x07,0x00,0x09,0x0A,0x0B,0x00,0x0D,0x0E,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x10,0x11,0x00,0x1C,0x14,0x15,
0x00,0x00,0x12,0x13,0x00,0x1F,0x16,0x17,0x00,0x19,0x1A,0x1B,0x00,0x1D,0x1E,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC8,0xC0,0xC1,0x00,0xCC,0xC4,0xC5,
0x00,0x00,0xC2,0xC3,0x00,0xCF,0xC6,0xC7,0x00,0xC9,0xCA,0xCB,0x00,0xCD,0xCE,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x40,0x41,0x00,0x4C,0x44,0x45,
0x00,0x00,0x42,0x43,0x00,0x4F,0x46,0x47,0x00,0x49,0x4A,0x4B,0x00,0x4D,0x4E,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x50,0x51,0x00,0x5C,0x54,0x55,
0x00,0x00,0x52,0x53,0x00,0x5F,0x56,0x57,0x00,0x59,0x5A,0x5B,0x00,0x5D,0x5E,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x20,0x21,0x00,0x2C,0x24,0x25,
0x00,0x00,0x22,0x23,0x00,0x2F,0x26,0x27,0x00,0x29,0x2A,0x2B,0x00,0x2D,0x2E,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x30,0x31,0x00,0x3C,0x34,0x35,
0x00,0x00,0x32,0x33,0x00,0x3F,0x36,0x37,0x00,0x39,0x3A,0x3B,0x00,0x3D,0x3E,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xF0,0xF1,0x00,0xFC,0xF4,0xF5,
0x00,0x00,0xF2,0xF3,0x00,0xFF,0xF6,0xF7,0x00,0xF9,0xFA,0xFB,0x00,0xFD,0xFE,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x60,0x61,0x00,0x6C,0x64,0x65,
0x00,0x00,0x62,0x63,0x00,0x6F,0x66,0x67,0x00,0x69,0x6A,0x6B,0x00,0x6D,0x6E,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x70,0x71,0x00,0x7C,0x74,0x75,
0x00,0x00,0x72,0x73,0x00,0x7F,0x76,0x77,0x00,0x79,0x7A,0x7B,0x00,0x7D,0x7E,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x90,0x91,0x00,0x9C,0x94,0x95,
0x00,0x00,0x92,0x93,0x00,0x9F,0x96,0x97,0x00,0x99,0x9A,0x9B,0x00,0x9D,0x9E,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xA0,0xA1,0x00,0xAC,0xA4,0xA5,
0x00,0x00,0xA2,0xA3,0x00,0xAF,0xA6,0xA7,0x00,0xA9,0xAA,0xAB,0x00,0xAD,0xAE,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB8,0xB0,0xB1,0x00,0xBC,0xB4,0xB5,
0x00,0x00,0xB2,0xB3,0x00,0xBF,0xB6,0xB7,0x00,0xB9,0xBA,0xBB,0x00,0xBD,0xBE,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD8,0xD0,0xD1,0x00,0xDC,0xD4,0xD5,
0x00,0x00,0xD2,0xD3,0x00,0xDF,0xD6,0xD7,0x00,0xD9,0xDA,0xDB,0x00,0xDD,0xDE,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE8,0xE0,0xE1,0x00,0xEC,0xE4,0xE5,
0x00,0x00,0xE2,0xE3,0x00,0xEF,0xE6,0xE7,0x00,0xE9,0xEA,0xEB,0x00,0xED,0xEE,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
ULONG data;
/* Fetch a longword at a word address using bitptr */
data=*(ULONG*)(RawBuffer+(bitptr>>3 & ~1));
/* Right-adjust and mask */
data >>= 22-(bitptr & 15);
data &= 1023;
bitptr += 10;
return GCRTable[data];
}
/* Scan for sync mark from bitptr. Returns TRUE if sync found.
We look for 9 1-bits (minimum to distinguish from normal data) starting on a byte
alignment. Consequently there must be at least 16 1-bits physically on the disk.
*/
static bool ScanSync(void)
{
UBYTE *ptr;
unsigned offset;
ptr=RawBuffer+(bitptr>>3);
if (bitptr&7) ptr++;
if (ptr >= RawBuffer+RAWBUFSIZE) return FALSE;
while (1) {
while (*ptr != 0xFF) {
++ptr;
if (ptr >= RawBuffer+RAWBUFSIZE) return FALSE;
}
++ptr;
if (ptr >= RawBuffer+RAWBUFSIZE) return FALSE;
if (*ptr & 0x80) break;
}
while (*ptr == 0xFF) {
++ptr;
if (ptr >= RawBuffer+RAWBUFSIZE) return FALSE;
}
if (*ptr == 0xFE) offset=7;
else if ((*ptr&0xFC)==0xFC) offset=6;
else if ((*ptr&0xF8)==0xF8) offset=5;
else if ((*ptr&0xF0)==0xF0) offset=4;
else if ((*ptr&0xE0)==0xE0) offset=3;
else if ((*ptr&0xC0)==0xC0) offset=2;
else if ((*ptr&0x80)==0x80) offset=1;
else offset=0;
bitptr=(ptr-RawBuffer)*8 + offset;
return TRUE;
}
static void ReadAndDecodeTrack(unsigned track, char *DecodedBuffer)
{
unsigned NeedMap, ReadMap;
unsigned drivetrack; /* 1541 track# */
unsigned SectorsPerTrack;
int retry;
UBYTE *secptr;
unsigned sec;
ULONG *longsecptr;
drivetrack=track/2 + 1;
/* Set bufbase, SectorsPerTrack, and DecodedBuffer */
if (drivetrack < 18) { /* zone 1 */
SectorsPerTrack=21; DecodedBuffer+=(drivetrack-1)*21*256; NeedMap=(1<<21)-1;
}
else if (drivetrack < 25) { /* zone 2 */
SectorsPerTrack=19; DecodedBuffer+=357*256+(drivetrack-18)*19*256; NeedMap=(1<<19)-1;
}
else if (drivetrack < 31) { /* zone 3 */
SectorsPerTrack=18; DecodedBuffer+=490*256+(drivetrack-25)*18*256; NeedMap=(1<<18)-1;
}
else { /* zone 4 */
SectorsPerTrack=17; DecodedBuffer+=598*256+(drivetrack-31)*17*256; NeedMap=(1<<17)-1;
}
ReadMap=0;
for (retry=RetryCount; (ReadMap != NeedMap) && (retry>=0); retry--) {
bitptr=0;
RawRead(track);
while (ReadMap != NeedMap) {
/* decode sector */
UBYTE checksum, sectornum, tracknum, id1, id2;
unsigned i;
if (!ScanSync()) break;
if (bitptr > MAXBITPTR) break;
if (GetByte() != 0x08) continue; /* if not header, restart */
checksum=GetByte(); sectornum=GetByte(); tracknum=GetByte(); id1=GetByte(); id2=GetByte();
if (checksum^tracknum^sectornum^id1^id2) continue;
if (sectornum >= SectorsPerTrack) {
printf("Sector number out of range on track %d\n",drivetrack);
continue;
}
if (tracknum != drivetrack) {
printf("Wrong track number (%d) on track %d\n",(int)tracknum,drivetrack);
continue;
}
if (ReadMap & (1<<sectornum)) continue; /* already read 'em */
/* Header looks good. Onto the data block. */
if (!ScanSync()) break;
if (bitptr > MAXBITPTR) break;
if (GetByte() != 0x07) continue; /* if not data block, restart */
secptr=DecodedBuffer+(sectornum*256);
checksum=0;
for (i=0; i <= 255; i++) {
*secptr=GetByte(); checksum ^= *secptr; secptr++;
}
if (GetByte() == checksum) {
ReadMap |= 1<<sectornum;
}
}
if (ReadMap != NeedMap) {
printf("Trouble reading track %d\n",drivetrack);
}
}
if (ReadMap == NeedMap) {
// printf("Track %d read successfully\n",drivetrack);
return;
}
/* We couldn't read one or more sectors on this track. Print out some info and
mark the bad sectors with a special identifier */
printf("Bad sectors on track %d: ",drivetrack);
for (sec=0; sec < SectorsPerTrack; sec++) {
unsigned i;
if (!(ReadMap & 1<<sec)) {
printf("%d, ",sec);
secptr=DecodedBuffer+(sec*256);
longsecptr=(ULONG*)secptr;
for (i=0; i <= 63; i++) {
longsecptr[i]=0;
}
secptr[1]=0xFF;
strcpy(secptr+2,"LAZARUS");
}
}
printf("\b\b \n");
}
/* Returns TRUE if successful */
static bool WriteFile(char *filename, char *buffer, unsigned size)
{
BPTR file;
LONG actual;
file=Open(filename,MODE_NEWFILE); if (!file) return FALSE;
actual=Write(file,buffer,size);
Close(file);
if (actual != size) return FALSE;
return TRUE;
}
void main(void)
{
unsigned track;
printf("1541 - Copyright © 1994 by Dan Babcock\n");
/* Handle command-line arguments */
rdargs=ReadArgs("DRIVE/N/A,FILENAME/A,RETRY/K/N,TOP/S,OFFSET/K/N",args,0);
if (rdargs == 0) {
printf("Invalid parameters\n");
return;
}
if (args[RETRY]) RetryCount=*(unsigned*)args[RETRY];
/* Set up for trackdisk I/O */
DiskBase=OpenResource("disk.resource");
if ((port = CreateMsgPort())==0) {
printf("Could not create message port (out of memory)\n");
return;
}
if ((io = CreateIORequest(port,sizeof(struct IOStdReq)))==0) {
printf("Could not create IORequest (out of memory)\n");
return;
}
if (OpenDevice("trackdisk.device", *(int *)args[DRIVE], (struct IORequest *)io, TDF_ALLOW_NON_3_5)) {
printf("Could not open trackdisk unit %d\n",*(int *)args[DRIVE]);
return;
}
DevOpen = TRUE;
/* Read and decode */
if (!args[TOP])
for (track=0; track <= 68; track+=2)
ReadAndDecodeTrack(track, DecodedBuffer);
else
for (track=1; track <= 69; track+=2)
ReadAndDecodeTrack(track, DecodedBuffer);
/* Write image to file */
if (!WriteFile((char *)args[FILENAME],DecodedBuffer,DISKSIZE)) {
printf("Error writing image file\n");
}
}